/**
 *    Copyright (C) 2011 Nadim Benabdenbi <nadim.benabdenbi@gmail.com>
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.google.code.maven.plugin.beans.builder;

import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.List;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;

import com.sun.codemodel.JClassAlreadyExistsException;
import com.sun.codemodel.JCodeModel;

/**
 * Generates Builder for a defined beans set.
 * 
 * @author <a href="mailto:nadim.benabdenbi@gmail.com">Nadim Benabdenbi</a>
 * @version 1.0
 * @since JDK1.6
 * 
 * @phase generate-sources
 * @goal builders
 */
public class BeansBuilderGeneratorMojo extends AbstractMojo {
	
	/**
	 * the generated source path.
	 * 
	 * @parameter default-value="target/generated-sources/builders/java"
	 */
	private String generatedSourcesPath = "target/generated-sources/builders/java";
	
	/**
	 * the beans builder to generate.
	 * 
	 * @parameter
	 * @required
	 */
	private List<String> beans;
	
	/**
	 * The Maven project
	 * 
	 * @parameter expression="${project}"
	 * @required
	 */
	private MavenProject project;
	
	public void execute() throws MojoExecutionException, MojoFailureException {
		// creates builder sources directory
		File sources = new File(generatedSourcesPath);
		// creating the path if necessary
		if (!sources.exists() && !sources.mkdirs()) {
			throw new MojoExecutionException("failed to makes sources directory " + generatedSourcesPath);
		}
		// add the source path to the project compile source root
		project.addCompileSourceRoot(generatedSourcesPath);
		// source generation starts
		getLog().info(MessageFormat.format("generating builders under source path [{0}]", generatedSourcesPath));
		// common code model
		JCodeModel codeModel = new JCodeModel();
		for (String className : beans) {
			try {
				Class<?> javaType = Thread.currentThread().getContextClassLoader().loadClass(className);
				getLog().info("generating builder for " + className);
				new ReflectionBuilderSourceGenerator(codeModel, javaType).generate();
			} catch (ClassNotFoundException cnfe) {
				throw new MojoExecutionException("class not found " + className);
			} catch (JClassAlreadyExistsException caee) {
				throw new MojoExecutionException("Failed to generate builder: cycle failure", caee);
			}
		}
		try {
			// building the code model
			codeModel.build(sources);
		} catch (IOException io) {
			throw new MojoFailureException("Failed to write generated sources to" + generatedSourcesPath, io);
		}
	}
	
	/**
	 * @return the generatedSourcesPath
	 */
	public String getGeneratedSourcesPath() {
		return generatedSourcesPath;
	}
	
	/**
	 * @param generatedSourcesPath
	 *            the generatedSourcesPath to set
	 */
	public void setGeneratedSourcesPath(String generatedSourcesPath) {
		this.generatedSourcesPath = generatedSourcesPath;
	}
	
	/**
	 * @return the targets
	 */
	public List<String> getTargets() {
		return beans;
	}
	
	/**
	 * @param targets
	 *            the targets to set
	 */
	public void setTargets(List<String> targets) {
		this.beans = targets;
	}
	
	/**
	 * @return the project
	 */
	public MavenProject getProject() {
		return project;
	}
	
	/**
	 * @param project
	 *            the project to set
	 */
	public void setProject(MavenProject project) {
		this.project = project;
	}
	
}
